package displayboardinfo.services;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBElement;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.exception.ConstraintViolationException;

import com.sun.jersey.api.client.ClientResponse.Status;

import displayboardinfo.entities.RegisteredForUpdates;

/**
 * Klasa odpowiedzialna za wystawianie usług związanych z zapisaniem i wypisaniem się z grupy klientów informowanych o zmianach w gabinecie.
 * 
 * @author Artur Jaworski
 */
@Path("/updates")
public class UpdatesServices {
	/**
	 * Usługa zapisania się do grupy klientów informowanych o zmianach w gabinecie (dodanie, modyfikacja, zakończenie wizyty)
	 * Usługa dostępna jest na serwerze pod adresem /updates/register używając metody POST.
	 * Usługa zwraca kod 200 [OK] gdy wywołanie się powiedzie lub kod 406 [NOT ACCEPTABLE] gdy wystąpi błąd (błąd serwera).
	 * Przy wystąpieniu błędu do odpowiedzi dołączany jest krótki opis przyczyny błędu.
	 * W przypadku gdy para (IP,port) występuje już w bazie danych, zostaje ona nadpisana przesyłaną parą.
	 * 
	 * @param registeredJaxb obiekt reprezentujący przypisanie do aktualizacji gabinetu, w formie koperty XML
	 * @return pusta odpowiedź, zawierająca kod i komunikat o błędzie w przypadku niepowodzenia
	 */
	@SuppressWarnings("deprecation")
	@Path("/register")
	@POST
	@Consumes(MediaType.APPLICATION_XML)
	public Response register(JAXBElement<RegisteredForUpdates> registeredJaxb) {
		RegisteredForUpdates registered = registeredJaxb.getValue();
		SessionFactory sf = new Configuration().configure().buildSessionFactory();
		Session session = sf.openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.save(registered);
			transaction.commit();
			return Response.ok().build();
		} catch (ConstraintViolationException e) { 
			transaction.rollback();
			session.close();
			session = sf.openSession();
			transaction = session.beginTransaction();
			session.createQuery("delete from RegisteredForUpdates r where r.ip = :ip and r.port = :port").setParameter("ip", registered.getIp()).setParameter("port", registered.getPort()).executeUpdate();
			session.save(registered);
			transaction.commit();
			return Response.ok().build();
		} catch (Exception e) {
			transaction.rollback();
			throw new WebApplicationException(Response
					.status(Status.NOT_ACCEPTABLE).entity("Nieznany błąd")
					.type(MediaType.TEXT_PLAIN).build());
		} finally {
			session.close();
			sf.close();
		}

	}

	/**
	 * Usługa wypisania się z grupy klientów informowanych o zmianach w gabinecie (dodanie, modyfikacja, zakończenie wizyty)
	 * Usługa dostępna jest na serwerze pod adresem /updates/unregister używając metody POST.
	 * Usługa zwraca kod 200 [OK] gdy wywołanie się powiedzie lub kod 406 [NOT ACCEPTABLE] gdy wystąpi błąd (błąd serwera).
	 * Przy wystąpieniu błędu do odpowiedzi dołączany jest krótki opis przyczyny błędu.
	 * 
	 * @param registeredJaxb obiekt reprezentujący przypisanie do aktualizacji gabinetu, w formie koperty XML
	 * @return pusta odpowiedź, zawierająca kod i komunikat o błędzie w przypadku niepowodzenia
	 */
	@SuppressWarnings("deprecation")
	@Path("/unregister")
	@POST
	@Consumes(MediaType.APPLICATION_XML)
	public Response unregister(JAXBElement<RegisteredForUpdates> registeredJaxb) {
		RegisteredForUpdates registered = registeredJaxb.getValue();
		SessionFactory sf = new Configuration().configure().buildSessionFactory();
		Session session = sf.openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.createQuery("delete from RegisteredForUpdates r where r.ip = :ip and r.port = :port").setParameter("ip", registered.getIp()).setParameter("port", registered.getPort()).executeUpdate();
			transaction.commit();
			return Response.ok().build();
		} catch (Exception e) {
			transaction.rollback();
			throw new WebApplicationException(Response
					.status(Status.NOT_ACCEPTABLE).entity("Nieznany błąd")
					.type(MediaType.TEXT_PLAIN).build());
		} finally {
			session.close();
			sf.close();
		}

	}

}
